// --------------------------------------------------------------------------------------------------------------------
// <copyright file="KinectDepthCameraParameters.cs" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Microsoft.Robotics.Vision.Cameras
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.Text;
    using System.Threading.Tasks;

    using Microsoft.Kinect;
    using Microsoft.Robotics.Numerics;

    /// <summary>
    /// Container for the parameters of a the Kinect depth camera
    /// </summary>
    [DataContract]
    public class KinectDepthCameraParameters : DepthParameters
    {
        /// <summary>
        /// Initializes a new instance of the KinectDepthCameraParameters class
        /// </summary>
        /// <param name="intrinsics">The camera intrinsics</param>
        /// <param name="distortion">The lens distortion parameters</param>
        /// <param name="horizontalFieldOfViewInRadians">The horizontal field of view in radians</param>
        /// <param name="verticalFieldOfViewInRadians">The vertical field of view in radians</param>
        /// <param name="depthImageFormat">The format of the depth image</param>
        /// <param name="maxDepth">The max depth seen by the sensor</param>
        /// <param name="minDepth">The min depth seen by the sensor</param>
        /// <param name="range">The range of depths seen by the sensor</param>
        /// <param name="tooFarDepth">The too far value</param>
        /// <param name="tooNearDepth">The too near value</param>
        /// <param name="unknownDepth">The unknown depth value</param>
        /// <param name="leftRight">If true, then images are left right</param>
        /// <param name="state">The state of the kinect</param>
        /// <param name="alignmentParameters">The alignment parameters</param>
        public KinectDepthCameraParameters(
            Matrix3 intrinsics,
            LensDistortion distortion,
            double horizontalFieldOfViewInRadians,
            double verticalFieldOfViewInRadians,
            DepthImageFormat depthImageFormat,
            short maxDepth,
            short minDepth,
            DepthRange range,
            short tooFarDepth,
            short tooNearDepth,
            short unknownDepth,
            bool leftRight,
            KinectCameraState state,
            ReadOnlyCollection<byte> alignmentParameters)
            : base(
            intrinsics: intrinsics,
            lensDistortion: distortion,
            horizontalFieldOfViewInRadians: horizontalFieldOfViewInRadians,
            verticalFieldOfViewInRadians: verticalFieldOfViewInRadians,
            tooFar: tooFarDepth,
            tooNear: tooNearDepth)
        {
            this.DepthImageFormat = depthImageFormat;
            this.MaxDepth = maxDepth;
            this.MinDepth = minDepth;
            this.Range = range;
            this.UnknownDepth = unknownDepth;
            this.LeftRightImage = leftRight;
            this.State = state;

            if (null != alignmentParameters)
            {
                this.AlignmentParameters = alignmentParameters.ToArray();
            }
        }

        /// <summary>
        /// Initializes a new instance of the KinectDepthCameraParameters class
        /// </summary>
        /// <param name="baseParameters">Base depth parameter values</param>
        /// <param name="depthImageFormat">The format of the depth image</param>
        /// <param name="range">The range of depths seen by the sensor</param>
        /// <param name="leftRight">If true, then images are left right</param>
        /// <param name="state">The state of the kinect</param>
        /// <param name="alignmentParameters">The alignment parameters</param>
        public KinectDepthCameraParameters(
            DepthParameters baseParameters,
            DepthImageFormat depthImageFormat = Microsoft.Kinect.DepthImageFormat.Undefined,
            DepthRange range = DepthRange.Default,
            bool leftRight = true,
            KinectCameraState state = null,
            ReadOnlyCollection<byte> alignmentParameters = null)
            : base(baseParameters)
        {
            this.DepthImageFormat = depthImageFormat;
            this.MaxDepth = baseParameters.TooFarDepth;
            this.MinDepth = baseParameters.TooNearDepth;
            this.Range = range;
            this.UnknownDepth = baseParameters.NoReadingValue;
            this.LeftRightImage = leftRight;
            this.State = state;

            if (null != alignmentParameters)
            {
                this.AlignmentParameters = alignmentParameters.ToArray();
            }
        }

        /// <summary>
        /// Gets The format of the depth image
        /// </summary>
        [DataMember]
        public DepthImageFormat DepthImageFormat { get; private set; }

        /// <summary>
        /// Gets The maximum reliable depth
        /// </summary>
        [DataMember]
        public short MaxDepth { get; private set; }

        /// <summary>
        /// Gets The minimum reliable depth
        /// </summary>
        [DataMember]
        public short MinDepth { get; private set; }

        /// <summary>
        /// Gets The range at which the kinect is operating (Default or near)
        /// <see cref="DepthRange"/>
        /// </summary>
        [DataMember]
        public DepthRange Range { get; private set; }

        /// <summary>
        /// Gets Unknown depth
        /// </summary>
        [DataMember]
        public short UnknownDepth { get; private set; }

        /// <summary>
        /// Gets the state of the camera
        /// </summary>
        [DataMember]
        public KinectCameraState State { get; private set; }

        /// <summary>
        /// Gets the alignment parameters
        /// </summary>
        [DataMember]
        public byte[] AlignmentParameters { get; private set; }

        /// <summary>
        /// Gets a value indicating whether the images are left right or not
        /// </summary>
        [DataMember]
        public bool LeftRightImage { get; private set; }

        /// <summary>
        /// Returns the alignment parameters for a kinect color and depth image
        /// </summary>
        /// <returns>The alignment parameters</returns>
        public override object GetAlignmentParameters()
        {
            return (object)this.AlignmentParameters;
        }
    }
}
